package com.rockcent.service.impl;

import com.rockcent.common.common.PageResult;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.mall.lib.domain.*;
import com.rockcent.mall.lib.dto.CustomerDto;
import com.rockcent.mall.lib.repository.*;
import com.rockcent.service.MallService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class MallServiceImpl implements MallService {

    private final Logger log = LoggerFactory.getLogger(MallServiceImpl.class);
    @Autowired
    private ProductEventRepository productEventRepository;
    @Autowired
    private MerchantProductCategoriesRepository merchantProductCategoriesRepository;
    @Autowired
    private MerchantProductRepository merchantProductRepository;

    @Autowired
    private FavoriteRepository favoriteRepository;

    @Autowired
    private RecommendRepository recommendRepository;

    /**
     * 首页推荐，算法思路如下：
     * 所以先将几种规则的产品查询出来，然后合并后去重，
     *
     * @param pageNo
     * @param pageSize
     * @param customerDto
     * @return
     */
    @Override
    public PageResult<Product> getAdvising(Integer pageNo, Integer pageSize, CustomerDto customerDto) {


        PageResult<Product> productPageResult = new PageResult<>(pageNo, pageSize);

//        log.info("查找当前用户的首页推荐商品,id:{},name:{}", customerDto.getId(), customerDto.getNickName());

        Long mallId = customerDto.getMallId();
        Long customerId = customerDto.getId();

        //1.最近浏览产品的同类目产品销量top10，按浏览时间从后往前依次推荐，浏览行为取仅三个月
        List<Long> products1 = getAdvisingByViewedProductTop10Limit1000(mallId, customerId, Whether.NO);
        log.info("1.最近浏览产品的同类目产品销量top10，按浏览时间从后往前依次推荐，浏览行为取仅三个月:{}", null != products1 ? products1.size() : null);

        //2.用户收藏产品的同类目产品销量top10，按收藏时间从后往前依次推荐
        List<Long> products2 = getAdvisingByCollectedProductTop10Limit1000(mallId, customerId, Whether.NO);
        log.info("2.用户收藏产品的同类目产品销量top10，按收藏时间从后往前依次推荐:{}", null != products2 ? products2.size() : null);


        //3.平台推荐商家产品销量top20，含自营+分销
        List<Long> products3 = getAdvisingByRecommendMerchantProductTop20Limit1000(mallId, customerId, Whether.NO);

        log.info("3.平台推荐商家产品销量top20，含自营+分销:{}", null != products3 ? products3.size() : null);

        //4.全平台销量top50
        List<Long> products4 = getAdvisingByMaxSaledProductTop50Limit1000(mallId, customerId, Whether.NO);
        log.info("4.全平台销量top50:{}", null != products4 ? products4.size() : null);

        //5.剩余全平台产品按最新上架时间，仅显示自营产品
        List<Long> products5 = getAdvisingByProductsLimit1000ByDateCreatedDesc(mallId, customerId, Whether.NO);

        log.info("5.剩余全平台产品按最新上架时间，仅显示自营产品:{}", null != products5 ? products5.size() : null);

        //合并去重
        Set<Long> uniqueProducts = new LinkedHashSet<>();
        uniqueProducts.addAll(products1);
        uniqueProducts.addAll(products2);
        uniqueProducts.addAll(products3);
        uniqueProducts.addAll(products4);
        uniqueProducts.addAll(products5);


        List<Long> uniqueProductList = new ArrayList<>(uniqueProducts);
        //根据productID判断是否已经下架，若下架则在uniqueProductList里去掉。


        //分页
        List<Long> currentPageProductIds = uniqueProductList.subList(pageNo * pageSize, pageNo * pageSize + pageSize);


        //查询数据
        List<Product> datas = merchantProductRepository.findByIdInAndMallId(currentPageProductIds, mallId);
        productPageResult.setData(datas);
        productPageResult.setTotalCount(uniqueProductList.size());


        return productPageResult;
    }

    /**
     * 4.全平台销量top50
     *
     * @param mallId
     * @param customerId
     * @param no
     * @return
     */
    private List<Long> getAdvisingByMaxSaledProductTop50Limit1000(Long mallId, Long customerId, Whether no) {
        List<Product> products = merchantProductRepository.findByMallIdAndIsDelete(mallId, Whether.NO);
        //去掉已下架的
        List<Product> products1 = products.stream().filter(product -> "SELLING".equals(product.getStatus().toString())).collect(Collectors.toList());
        List<Long> productIdList = products1.stream().map(Product::getId).collect(Collectors.toList());
        return productEventRepository.findTop10ProductsOderbyTotalSaled(productIdList);
    }

    /**
     * 5.剩余全平台产品按最新上架时间，仅显示自营产品
     *
     * @param mallId
     * @param customerId
     * @param no
     * @return
     */
    private List<Long> getAdvisingByProductsLimit1000ByDateCreatedDesc(Long mallId, Long customerId, Whether no) {
        List<Product> products = merchantProductRepository.findByMallIdAndIsDeleteOrderByIdDesc(mallId, Whether.NO);
        //去掉已下架的
        List<Product> products1 = products.stream().filter(product -> "SELLING".equals(product.getStatus().toString())).collect(Collectors.toList());
        List<Long> productIdList = products1.stream().map(Product::getId).collect(Collectors.toList());
        return productIdList;
    }

    /**
     * 3.平台推荐商家产品销量top20，含自营+分销
     *
     * @param mallId
     * @param customerId
     * @param no
     * @return
     */
    private List<Long> getAdvisingByRecommendMerchantProductTop20Limit1000(Long mallId, Long customerId, Whether no) {

        List<Recommend> recommends = recommendRepository.findByMallIdAndIsDelete(mallId, Whether.NO);
        List<Long> merchantIds = recommends.stream().map(Recommend::getMerchantId).collect(Collectors.toList());
        List<Product> products = merchantProductRepository.findByMallIdAndMerchantIdInAndIsDelete(mallId, merchantIds, Whether.NO);
       //去掉已下架的
        List<Product> products1 = products.stream().filter(product -> "SELLING".equals(product.getStatus().toString())).collect(Collectors.toList());
        List<Long> productIdList = products1.stream().map(Product::getId).collect(Collectors.toList());
        return productEventRepository.findTop10ProductsOderbyTotalSaled(productIdList);
    }

    /**
     * 2.用户收藏产品的同类目产品销量top10，按收藏时间从后往前依次推荐
     *
     * @param mallId
     * @param customerId
     * @param no
     * @return
     */
    private List<Long> getAdvisingByCollectedProductTop10Limit1000(Long mallId, Long customerId, Whether no) {

        List<Long> productIdList = favoriteRepository.getAllFavoriteProductsOrderByDateDesc(customerId, mallId);


        List<Long> productsInTotalSaled = getProductsByCategoryIds(productIdList);


        return productsInTotalSaled;
    }

    /**
     * 1.最近浏览产品的同类目产品销量top10，按浏览时间从后往前依次推荐，浏览行为取仅三个月
     *
     * @param mallId
     * @param customerId
     * @param no
     * @return
     */
    private List<Long> getAdvisingByViewedProductTop10Limit1000(Long mallId, Long customerId, Whether no) {
        //三个月的浏览记录
        List<Long> productIdList = productEventRepository.getTop10WithinThreeMonths(customerId, mallId);
        List<Long> productsInTotalSaled = getProductsByCategoryIds(productIdList);


        return productsInTotalSaled;
    }

    /**
     * 通过产品类目找产品
     *
     * @param productIdList
     * @return
     */
    private List<Long> getProductsByCategoryIds(List<Long> productIdList) {
        //包含产品的类目
        List<ProductCategories> productCategoriesList = merchantProductCategoriesRepository.findByProductIdIn(productIdList);

        List<Long> categoriesId = productCategoriesList.stream().map(ProductCategories::getCategoryId).collect(Collectors.toList());
        //类目所有的产品
        List<ProductCategories> productCategoriesList2 = merchantProductCategoriesRepository.findByCategoryIdIn(categoriesId);

        productIdList = productCategoriesList2.stream().map(ProductCategories::getProductId).collect(Collectors.toList());
        //去掉已下架的
        List<Product> products = merchantProductRepository.findByIdIn(productIdList);
        List<Product> products1 = products.stream().filter(product -> "SELLING".equals(product.getStatus().toString())).collect(Collectors.toList());
        productIdList = products1.stream().map(Product::getId).collect(Collectors.toList());
        if (null == productIdList || productIdList.isEmpty()) {
            return new ArrayList<>();
        }
        return productEventRepository.findTop10ProductsOderbyTotalSaled(productIdList);
    }
}
